﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Nature
{
    [AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
    public sealed class MixturePropertyAttribute : System.Attribute
    {
        
    }
    

    struct ValueHolder
    {
        double m_value;
        internal bool UpToDate { get; set; }
        internal double Value 
        {
            get 
            {
                Debug.Assert(this.UpToDate);
                return m_value; 
            }
            set { m_value = value; UpToDate = true; }
        }
    }

    [Serializable]
    struct DoubleArrayHolder
    {
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        double[] m_array;

        internal bool UpToDate
        {
            get;
            set;
        }
        
        public double[] Array
        {
            [DebuggerNonUserCode]
            get 
            {
                return m_array ?? (m_array = new double[Size]);
            }
        }

        internal int Size
        {
            get;
            private set;
        }

        internal DoubleArrayHolder(int length)
            : this()
        {
            this.Size = length;
        }

        internal void Assign(double[] values)
        {
            var array = this.Array;
            for (int i = 0; i < Size; ++i)
            {
                array[i] = values[i];
            }
            UpToDate = true;
        }

        internal void Assign(decimal[] values)
        {
            var array = this.Array;
            for (int i = 0; i < Size; ++i)
            {
                array[i] = (double)values[i];
            }
            UpToDate = true;
        }

        internal void Assign(double[] values, Func<int, int> convertToNativeIndex, double defaultValue = 0d)
        {
            var array = this.Array;
            for (int i = 0; i < Size; ++i)
            {
                array[i] = defaultValue;
            }
            for (int i = 0; i < values.Length; ++i)
            {
                array[convertToNativeIndex(i)] = values[i];
            }
            UpToDate = true;
        }
    }


    [Serializable]
    public struct DoubleMatrixHolder
    {
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        double[][] m_matrix;
        Func<int, int> m_getDimension;

        internal DoubleMatrixHolder(int iLength, Func<int, int> getDimension) : this()
        {
            this.ILength = iLength;
            this.m_getDimension = getDimension;
        }

        internal bool UpToDate
        {
            get;
            set;
        }

        public double[][] Matrix
        {
            [DebuggerStepThrough()]
            get
            {
                if (m_matrix == null)
                {
                    m_matrix = new double[ILength][];
                    for (int i = 0; i < ILength; ++i)
                    {
                        int jLength = m_getDimension(i);
                        m_matrix[i] = new double[jLength];
                    }
                    m_getDimension = null;
                }
                return m_matrix;
            }
        }

        internal int ILength
        {
            get;
            private set;
        }
    }
    
}
